import { Text, View } from '@tarojs/components';
import { useField } from 'formik';
import theme from '@/theme';
import classNames from 'classnames';
import { ComponentProps, useContext } from 'react';
import { FormConfigContext } from '../Form/utils';
import type { FormProps } from '../Form';
import './index.scss';
import Input from '../Input';
import Switch from '../Switch';
import Textarea from '../Textarea';
import CheckboxGroup from '../CheckboxGroup';
import RadioGroup from '../RadioGroup';
import Select from '../Select';
import DateInput from '../DateInput';
import Picker from '../Picker';
import TimePicker from '../TimePicker';
import Cascader from '../Cascader';
import InputNumber from '../InputNumber';
import UploadFile from '../UploadFile';

type CustomComponentProps = {
  children: any;
};
export type FormItemProps = MutableRecord<{
  Component: CustomComponentProps;
  Input: ComponentProps<typeof Input>;
  InputNumber: ComponentProps<typeof InputNumber>;
  Textarea: ComponentProps<typeof Textarea>;
  Switch: ComponentProps<typeof Switch>;
  CheckboxGroup: ComponentProps<typeof CheckboxGroup>;
  RadioGroup: ComponentProps<typeof RadioGroup>;
  Select: ComponentProps<typeof Select>;
  DateInput: ComponentProps<typeof DateInput>;
  Picker: ComponentProps<typeof Picker>;
  TimePicker: ComponentProps<typeof TimePicker>;
  Cascader: ComponentProps<typeof Cascader>;
  UploadFile: ComponentProps<typeof UploadFile>;
}>;
type MutableRecord<U> = {
  [SubType in keyof U]: U[SubType] &
    Omit<
      {
        type: SubType;
        direction?: FormProps['direction'];
        labelWidth?: FormProps['labelWidth'];
        name: string;
        label?: string | JSX.Element;
        disabled?: boolean;
        staticed?: boolean;
        onChange?: (value: any) => any;
        placeholder?: string;
        className?: string;
        required?: boolean;
        /** 额外渲染的东西 */
        renderExtra?: string | JSX.Element;
        extraClassName?: string;
      },
      keyof U[SubType]
    >;
}[keyof U];

const test1: FormItemProps = {
  type: 'Textarea',
  name: '1',
  showCounter: true,
  onChange: value => {},
};

const FormItem = ({
  name,
  label,
  disabled,
  staticed,
  className,
  placeholder,
  direction,
  labelWidth,
  required = false,
  type,
  renderExtra,
  extraClassName,
  ...props
}: FormItemProps) => {
  const formConfig = useContext(FormConfigContext);
  if (typeof formConfig.disabled === 'boolean') {
    disabled = formConfig.disabled;
  }
  if (typeof formConfig.staticed === 'boolean') {
    staticed = formConfig.staticed;
  }
  if (typeof labelWidth !== 'number') {
    labelWidth = formConfig.labelWidth;
  }
  direction = direction || formConfig.direction || 'horizontal';
  const [field, meta, helpers] = useField(name);

  const commonProps = {
    ...props,
    value: field.value,
    onChange: e => {
      const tempValue = typeof e === 'object' ? e?.target?.value || e : e;
      formConfig.debug && console.log('formItem change', field.name, tempValue);
      field.onChange(field.name)(e);
      (props.onChange as any)?.(tempValue);
    },
    onBlur: field.onBlur(field.name),
    disabled: typeof formConfig.disabled === 'boolean' ? formConfig.disabled : disabled,
    staticed: typeof staticed === 'boolean' ? staticed : formConfig.staticed,
    placeholder,
  };
  return (
    <View
      className={classNames({
        'pd-formItem': true,
        'pd-formItem--vertical': direction === 'vertical',
        className: className,
      })}>
      <View
        className='pd-formItem__label'
        style={direction === 'horizontal' ? { minWidth: labelWidth, width: labelWidth, maxWidth: labelWidth } : {}}>
        <Text className='pd-formItem__label__required'>{required ? '*' : ' '}</Text>
        {label}
      </View>
      <View className='pd-formItem__content'>
        {type === 'Input' && <Input {...(props as any)} {...commonProps} />}
        {type === 'InputNumber' && (
          <InputNumber
            {...(props as any)}
            {...commonProps}
            onChange={value => {
              formConfig.debug && console.log('formItem change', field.name, { value });
              field.onChange(field.name)({ target: { value: value } } as any);
              (props.onChange as any)?.(value);
            }}
          />
        )}
        {type === 'Textarea' && <Textarea {...(props as any)} {...commonProps} />}
        {type === 'Switch' && (
          <Switch
            {...(props as any)}
            {...commonProps}
            onChange={e => {
              commonProps.onChange({ target: { value: e } } as any);
            }}
          />
        )}
        {type === 'CheckboxGroup' && (
          <CheckboxGroup
            {...(props as any)}
            {...commonProps}
            onChange={e => {
              commonProps.onChange({ target: { value: e } } as any);
            }}
          />
        )}
        {type === 'RadioGroup' && (
          <RadioGroup
            {...(props as any)}
            {...commonProps}
            onChange={e => {
              commonProps.onChange({ target: { value: e } } as any);
            }}
          />
        )}
        {type === 'Select' && (
          <Select
            {...(props as any)}
            {...commonProps}
            onChange={(value, item) => {
              formConfig.debug && console.log('formItem change', field.name, { value, item });
              field.onChange(field.name)({ target: { value: value } } as any);
              (props.onChange as any)?.(value, item);
            }}
          />
        )}
        {type === 'DateInput' && (
          <DateInput
            {...(props as any)}
            {...commonProps}
            onChange={e => {
              commonProps.onChange({ target: { value: e } } as any);
            }}
          />
        )}
        {type === 'Picker' && (
          <Picker
            {...(props as any)}
            {...commonProps}
            onChange={(value, item) => {
              formConfig.debug && console.log('formItem change', field.name, { value, item });
              field.onChange(field.name)({ target: { value: value } } as any);
              (props.onChange as any)?.(value, item);
            }}
          />
        )}
        {type === 'TimePicker' && (
          <TimePicker
            {...(props as any)}
            {...commonProps}
            onChange={(value, item) => {
              formConfig.debug && console.log('formItem change', field.name, { value, item });
              field.onChange(field.name)({ target: { value: value } } as any);
              (props.onChange as any)?.(value, item);
            }}
          />
        )}
        {type === 'Cascader' && (
          <Cascader
            {...(props as any)}
            {...commonProps}
            onChange={(value, item) => {
              formConfig.debug && console.log('formItem change', field.name, { value, item });
              field.onChange(field.name)({ target: { value: value } } as any);
              (props.onChange as any)?.(value, item);
            }}
          />
        )}
        {type === 'UploadFile' && (
          <UploadFile
            {...(props as any)}
            {...commonProps}
            onChange={e => {
              commonProps.onChange({ target: { value: e } } as any);
            }}
          />
        )}
        {type === 'Component' && (props as any).children}
      </View>
      {!!renderExtra && (
        <View
          className={classNames('pd-formItem__extra', extraClassName)}
          style={direction === 'horizontal' ? { paddingLeft: labelWidth } : {}}>
          {renderExtra}
        </View>
      )}
      {!!meta.error && (
        <View className='pd-formItem__error' style={direction === 'horizontal' ? { paddingLeft: labelWidth } : {}}>
          {meta.error}
        </View>
      )}
    </View>
  );
};
export default FormItem;
